/**
 * JSparrow - Une version numérique du jeu "Attention Pirates !" - Copyright (C) 2014 Black Pearl
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the
 * GNU General Public License as published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. If
 * not, see <http://www.gnu.org/licenses/>.
 */
package App.Vue;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

import App.Controleur.Jeu;
import App.Modele.Bateau;
import App.Modele.Joueur;
import App.Modele.Repaire;
import App.Modele.TypePiece;
public class Fenetre_Principale extends JFrame implements Observer {

	private Image table;
	private boolean flagInit = true;
	private Panneau_Menu menu;
	protected Jeu controleur;
	private Panneau_Jeu panneauJeu;
    private Panneau_ChargementPartie panneauChargerPartie;

	public Fenetre_Principale(Jeu controleur) {
		super();
		this.controleur = controleur;
		Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		this.setBounds(0, 0, screenBounds.width, screenBounds.height);

		this.setLocationRelativeTo(null);
		this.setExtendedState(JFrame.MAXIMIZED_BOTH);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setBackground(Color.BLUE);
		
		menu = new Panneau_Menu(this);
		this.setContentPane(menu);
		this.setVisible(true);
	}

	@Override
	public void update(Observable o, Object arg) {
			String s = (String) arg;
			s = s.replaceAll(" ", ""); // on enleve l espace
			String[] parts = s.split("=");
			String action = parts[0];

			if(action.equals("bateau")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a bateau
					bateauUpdate(parts[1]);
					/*
					 * TODO: Send new player if turn changed, and send bateau info.
					 */
				}
				else{
					System.out.println("bateau doit avoir un paramètre." );
				}
			}else if(action.equals("bateauCible")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a bateau
					bateauCibleUpdate(parts[1]);
					/*
					 * TODO: Send new player if turn changed, and send bateau info.
					 */
				}
				else{
					System.out.println("bateau doit avoir un paramètre." );
				}
			}
			else if(action.equals("repaire")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a repaire
					repaireUpdate(parts[1]);
				}
				else{
					System.out.println("repaire doit avoir un parametre." );
				}
			}
			else if(action.equals("credits")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a repaire
					creditUpdate(parts[1]);
				}
				else{
					System.out.println("credit doit avoir le nombre de credit en parametre." );
				}
			}
			else if(action.equals("listeBateaux")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a listeBateaux
					listeBateaux(parts[1]);
				}
				else{
					System.out.println("credit doit avoir le nombre de credit en parametre." );
				}
			}

			else if(action.equals("scores")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a listeBateaux
					scoresUpdate(parts[1]);
				}
				else{
					System.out.println("credit doit avoir le tableau des scores en parametre." );
				}
			}
			
			else if(action.equals("checkAttaque")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a listeBateaux
					checkAttaqueUpdate(parts[1]);
				}
				else{
					System.out.println("checkAttaque doit avoir le numero du bateau ou les coordonnees d'un repaire en parametre." );
				}
			}
			else if(action.equals("checkDeplace")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre
					checkDeplaceUpdate(parts[1]);
				}
				else{
					System.out.println("checkDeplace doit avoir les coordonnees d'un repaire en parametre." );
				}
			}
			else if(action.equals("checkReparer")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre
					checkReparerUpdate(parts[1]);
				}
				else{
					System.out.println("checkDeplace doit avoir les coordonnees d'un repaire en parametre." );
				}
			}
			else if(action.equals("parties")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a parties
					partiesUpdate(parts[1]);
				}
				else{
                    partiesUpdate("");
					System.out.println("parties doit avoir un parametre." );
				}
			}
			else if(action.equals("changementJoueur")){
				if(parts.length > 1 && parts.length < 3){ // on teste qu'il y a bien un parametre a parties
					changementJoueur(parts[1]);
				}
				else{
					System.out.println("parties doit avoir un parametre." );
				}
			}
			
	}
	
    /**
     * Change l'affichage de l'écran
     */
    public void chargerPartieClic() {
        this.controleur.envoiListeParties();
        this.setContentPane(this.panneauChargerPartie);
        this.pack();
        Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
        this.setBounds(0, 0, screenBounds.width, screenBounds.height);
        this.repaint();
    }
    
	/**
	 * Change l'affichage de l'écran
	 */
	public void creerPartieClic(){
		this.setContentPane(new Panneau_CreationPartie(this));
		this.pack();
		Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		this.setBounds(0, 0, screenBounds.width, screenBounds.height);
		this.repaint();
		
	}
	
	public void initialiserJeu(int nbJoueur){
		
		controleur.getPartieCourante().initialiser();
		panneauJeu = new Panneau_Jeu(controleur, nbJoueur);
		controleur.envoiScore();
		this.setContentPane(panneauJeu);
		this.pack();
		Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		this.setBounds(0, 0, screenBounds.width, screenBounds.height);
		this.repaint();
		
	}
	
	public void chargerJeu(int nbJoueur){
		
		panneauJeu = new Panneau_Jeu(controleur, nbJoueur);
		this.setContentPane(panneauJeu);
		this.pack();
		Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		this.setBounds(0, 0, screenBounds.width, screenBounds.height);
		this.repaint();
		
	}
	/**
	 * Envoie l'ordre de creer une partie
	 * @param nomPartie
	 * @param nbJoueur
	 */
	public void creerPartie(String nomPartie, int nbJoueur){
		controleur.creerPartie(nomPartie,nbJoueur);
	}
	
	/**
	 * Envoie l'ordre d'ajouter un joueur
	 * @param nom
	 */
	public void ajouterJoueur(String nom){
		controleur.ajouterJoueur(nom);
	}
	
	/**
	 * Affiche le menu principal
	 */
 	public void afficherMenu(){
		this.setContentPane(menu);
		this.pack();
		Rectangle screenBounds = GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
		this.setBounds(0, 0, screenBounds.width, screenBounds.height);
		this.repaint();
	}

 	/**
	 * methode qui decoupe une chaine de caractere representant le bateau pour l'envoyer a la vue correspondante
	 * @param bateauString
	 */
	public void bateauUpdate(String bateauString){
		String[] pieces_tresor_id = bateauString.split("_");
		if(pieces_tresor_id.length == 3){ // on verifie que le tableau contient bien 3 élements
			String[] tableauPieces = pieces_tresor_id[0].split("-"); // on a ici le tableau de piece
			if( pieces_tresor_id[1].matches("[0-9]")){
				String nbTresor = pieces_tresor_id[1];
				if( pieces_tresor_id[2].matches("[0-9]")){
					String idjoueur = pieces_tresor_id[2];
					System.out.println("Le bateau "+idjoueur+ " à "+nbTresor+ " trésors.");
					/** 
					 * TODO faire le lien avec la vue
					 */
					panneauJeu.updateBateauJoueur(idjoueur, tableauPieces, nbTresor);
				}
				else{
					System.out.println("L'id du joueur doit etre un nombre.");
				}
			}
			else{
				System.out.println("Le nombre de tresor doit etre un nombre.");
			}
			
			
		}
		else{
			System.out.println("Il n'y pas le bon nombre d'elements, il faut une partie piece, une partie nombre de trésors et une partie avec l'id du joueur");
		}
	}
	
	public void bateauCibleUpdate(String bateauString){
		String[] pieces_tresor_id = bateauString.split("_");
		if(pieces_tresor_id.length == 3){ // on verifie que le tableau contient bien 3 élements
			String[] tableauPieces = pieces_tresor_id[0].split("-"); // on a ici le tableau de piece
			if( pieces_tresor_id[1].matches("[0-9]")){
				String nbTresor = pieces_tresor_id[1];
				if( pieces_tresor_id[2].matches("[0-9]")){
					String idjoueur = pieces_tresor_id[2];
					System.out.println("Le bateau "+idjoueur+ " à "+nbTresor+ " trésors.");
					/** 
					 * TODO faire le lien avec la vue
					 */
					panneauJeu.updateBateauCible(idjoueur, tableauPieces, nbTresor);
				}
				else{
					System.out.println("L'id du joueur doit etre un nombre.");
				}
			}
			else{
				System.out.println("Le nombre de tresor doit etre un nombre.");
			}
			
			
		}
		else{
			System.out.println("Il n'y pas le bon nombre d'elements, il faut une partie piece, une partie nombre de trésors et une partie avec l'id du joueur");
		}
	}
	
	/**
	 * methode qui decoupe une chaine de caractere representant le repaire pour l'envoyer a la vue correspondante
	 * @param repaireString
	 */
	public void repaireUpdate(String repaireString){
		System.out.println("REPAIRE UPDATE ============================!!!!!");
		String[] pieces_tresor_id = repaireString.split("_");
		if(pieces_tresor_id.length == 3){ // on verifie que le tableau contient bien 3 élements
			String[] tableauPieces = pieces_tresor_id[0].split("-"); // on a ici le tableau de piece
			if( pieces_tresor_id[1].matches("[0-9]")){
				String nbTresor = pieces_tresor_id[1];
				if( pieces_tresor_id[2].matches("[0-9]")){
					String idRepaire = pieces_tresor_id[2];
					System.out.println("Le repaire "+idRepaire+ " à "+nbTresor+ " trésors.");
					/** 
					 * TODO faire le lien avec la vue
					 */
					panneauJeu.updateRepaireCible(Integer.parseInt(idRepaire), tableauPieces, Integer.parseInt(nbTresor));
				}
				else{
					System.out.println("L'id du joueur doit etre un nombre.");
				}
			}
			else{
				System.out.println("Le nombre de tresor doit etre un nombre.");
			}
		}
		else{
			System.out.println("Il n'y pas le bon nombre d'elements, il faut une partie piece, une partie nombre de trésors et une partie avec l'id du repaire");
		}
	}
	
	/**
	 * methode qui envoie le nombre de credit a la vue
	 * @param creditString
	 */
	public void creditUpdate(String creditString){
		String[] tableauCredit = creditString.split(";");
		if(tableauCredit[0].matches("[0-9]")){
			String nbCredit = tableauCredit[0];
			String[] pieces_tresor_id = tableauCredit[1].split("_");
			if(pieces_tresor_id.length == 3){ // on verifie que le tableau contient bien 3 élements
				String[] tableauPieces = pieces_tresor_id[0].split("-");
			System.out.println("la vue à recuperé "+nbCredit+ " crédits");
			panneauJeu.updateReparer(tableauPieces, Integer.parseInt(nbCredit));
			}
			/** 
			 * TODO faire le lien avec la vue
			 */
		}
		else{
			System.out.println("Le nombre de credit doit etre un nombre.");
			
		}
	}
	
	/**
	 * methode qui envoie la liste des bateaux aux vues
	 * @param listeBateauxString
	 */
	public void listeBateaux(String listeBateauxString){
		ArrayList<String[]> listeBateaux = new ArrayList<String[]>();
		String[] tableauBateaux = listeBateauxString.split("-"); // on a ici le tableau de piece
		for(int i = 0; i < tableauBateaux.length; i++){
			if(tableauBateaux[i].matches("\\([0-9];[0-9]\\)"))// test pour savoir si on a bien une coordonee en entrée
			{
				tableauBateaux[i] = tableauBateaux[i].replaceAll("\\(|\\)", ""); // on enleve les parantheses et les espaces
				String[] coordonneesString= tableauBateaux[i].split(";"); // on separe X et Y
				String[] bateau = {Integer.toString(i),coordonneesString[0],coordonneesString[1]};
				listeBateaux.add(bateau);			
			}
			else{
				System.out.println("Le parametre ne correspond pas a une coordonnée.");
			}
		}
		// TODO envoyer la liste au vue
		panneauJeu.updatePlateau(listeBateaux);
	}
 
	/**
	 * methode qui envoie les scores a la vue
	 * @param scoresString
	 */
	public void scoresUpdate(String scoresString){
		ArrayList<String[]> listeScores = new ArrayList<String[]>();
		String[] tableauJoueur = scoresString.split("_"); // on a ici le tableau des joueurs
		for(int i = 0; i < tableauJoueur.length; i++){
			String[] joueur = tableauJoueur[i].split("-"); // on a ici le tableau des joueurs
			listeScores.add(joueur);
		}
		panneauJeu.updateInformations(listeScores);
	}
	
	/**
	 * methode qui envoie la piece qui peut etre attaquee a la vue
	 * @param pieceString
	 */
	public void checkAttaqueUpdate(String pieceString){
		System.out.println(pieceString);
		boolean check = false;
		String[] tableaucheck = pieceString.split("_"); // on a ici le tableau des joueurs
		if(tableaucheck[1].matches("\\([0-9];[0-9]\\)") || tableaucheck[1].matches("[0-9]"))// si c'est un repaire ou un bateau qui est attaque
		{
			if(tableaucheck[0].equals("y")){
				System.out.println(tableaucheck[1] +", true");
				check = true;
				// TODO envoyer à la vue
				panneauJeu.updateAttaquer(check, tableaucheck[1]);
			}
			else if(tableaucheck[0].equals("n")){
				System.out.println(tableaucheck[1]+ ", false");
				check = false;
				// TODO envoyer à la vue
				panneauJeu.updateAttaquer(check, tableaucheck[1]);
			}
		}

		else{ // si le parametre ne contient pas un bateau ou un repaire
			System.out.println("Le parametre de checkAttaque ne correspond ni a un numero de joueur, ni a une coordonnee de repaire." );
		}
	}	
	
	/**
	 * methode qui envoie la piece qui peut etre attaquee a la vue
	 * @param coordonneeString
	 */
	public void checkDeplaceUpdate(String coordonneeString){
		boolean check = false;
		String[] tableaucheck = coordonneeString.split("_"); 
		if(tableaucheck[1].matches("\\([0-9];[0-9]\\)"))// si c'est un repaire qui est attaque
		{
			if(tableaucheck[0].equals("y")){
				System.out.println(tableaucheck[1] +", true");
				check = true;
				panneauJeu.updateDeplacer(check, tableaucheck[1]);
			}
			else if(tableaucheck[0].equals("n")){
				System.out.println(tableaucheck[1]+ ", false");
				check = false;
				panneauJeu.updateDeplacer(check, tableaucheck[1]);
			}
		}

		else{ // si le parametre ne contient pas un repaire
			System.out.println("Le parametre de checkDeplace ne correspond a une coordonnee de repaire." );
		}
	}
	
	public void checkReparerUpdate(String s){
			if(s.equals("y")){
				panneauJeu.updateReparer(true);
			}
			else if(s.equals("n")){
				panneauJeu.updateReparer(false);
			}
	}
    public void partiesUpdate(String listePartiesString) {
        if (listePartiesString.length() == 0) {
            this.panneauChargerPartie = new Panneau_ChargementPartie(new ArrayList<String>(), this.controleur, this);
        } else {
            // on a ici le tableau des parties
            String[] tableauPartie = listePartiesString.split("_");
            ArrayList<String> listeParties = new ArrayList<String>();
            for (int i = 0; i < tableauPartie.length; i++) {
                listeParties.add(tableauPartie[i]);
            }
            this.panneauChargerPartie = new Panneau_ChargementPartie(listeParties, this.controleur, this);
        }
    }
    
    public void changementJoueur(String nom){
		JOptionPane.showMessageDialog(this, "C'est à " + nom + " de jouer");
    }
}
